package boun.swe.bob.entities;

import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.comparators.ComparableComparator;
import org.apache.commons.collections.comparators.ReverseComparator;
import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * This entity corresponds to users table
 */
@Entity
@Table(name = "users")
public class User {

    @Id
    @GenericGenerator(name = "generator", strategy = "increment")
    @GeneratedValue(generator = "generator")
    @Column(name = "user_id")
    private Integer userId;

    @Column(name = "username")
    private String username;

    @Column(name = "password")
    private String password;

    @Column(name = "enabled")
    private Integer enabled;

    @Column(name = "name")
    private String name;

    @Column(name = "surname")
    private String surname;

    @Column(name = "latest_status")
    private String latestStatus;

    @Column(name = "location")
    private String location;

    @Column(name = "self_definition")
    private String selfDefinition;

    @Column(name = "image")
    private String image;

    @OneToOne
    @PrimaryKeyJoinColumn
    public Authority authority;

    @OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "user_id")
    @OrderBy("actionTime DESC")
    private Set<UserAction> actionList;

    @OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "user1_id", referencedColumnName = "user_id")
    @OrderBy("user1Id DESC")
    private Set<Friend> friends;

    @OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "requested_user_id", referencedColumnName = "user_id")
    private Set<FriendRequest> incomingFriendRequests;

    @OneToOne
    @PrimaryKeyJoinColumn
    public UserInfo userInfo;

    @ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
    @JoinTable(name = "group_member",joinColumns = { @JoinColumn(name = "member_user_id") },
       inverseJoinColumns = { @JoinColumn(name = "group_id") })
    private Set<Group> groups;

    @ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
    @JoinTable(name = "event_member",joinColumns = { @JoinColumn(name = "user_id") },
       inverseJoinColumns = { @JoinColumn(name = "event_id") })
    private Set<Bob_Event> events;



    @Transient
    private BeanComparator dateComparator;




    public User() {
        dateComparator = new BeanComparator("actionTime", new ReverseComparator(new ComparableComparator()));
    }

    public User(Integer userId, String username, String password, Integer enabled, String name, String surname, String latestStatus, String location, String selfDefinition, String image, Authority authority, Set<UserAction> actionList, Set<Friend> friends, Set<FriendRequest> incomingFriendRequests, UserInfo userInfo, Set<Group> groups, Set<Bob_Event> events, BeanComparator dateComparator) {
        this.userId = userId;
        this.username = username;
        this.password = password;
        this.enabled = enabled;
        this.name = name;
        this.surname = surname;
        this.latestStatus = latestStatus;
        this.location = location;
        this.selfDefinition = selfDefinition;
        this.image = image;
        this.authority = authority;
        this.actionList = actionList;
        this.friends = friends;
        this.incomingFriendRequests = incomingFriendRequests;
        this.userInfo = userInfo;
        this.groups = groups;
        this.events = events;
        this.dateComparator = dateComparator;
    }

    public Set<Bob_Event> getEvents() {
        return events;
    }

    public void setEvents(Set<Bob_Event> events) {
        this.events = events;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getEnabled() {
        return enabled;
    }

    public void setEnabled(Integer enabled) {
        this.enabled = enabled;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public String getLatestStatus() {
        return latestStatus;
    }

    public void setLatestStatus(String latestStatus) {
        this.latestStatus = latestStatus;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public Authority getAuthority() {
        return authority;
    }

    public void setAuthority(Authority authority) {
        this.authority = authority;
    }

    public String getSelfDefinition() {
        return selfDefinition;
    }

    public void setSelfDefinition(String selfDefinition) {
        this.selfDefinition = selfDefinition;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public List<UserAction> getActionList() {
        int limit = Math.min(actionList.size(), 15);
        List<UserAction> list = new ArrayList<UserAction>(actionList).subList(0, limit);
        Collections.sort(list, dateComparator);
        return list;
    }

    public void setActionList(Set<UserAction> actionList) {
        this.actionList = actionList;
    }

    public UserInfo getUserInfo() {
        return userInfo;
    }

    public void setUserInfo(UserInfo userInfo) {
        this.userInfo = userInfo;
    }
    /*
    public Set<UserMessage> getInboxList() {
        return inboxList;
    }

    public Set<UserMessage> getOutboxList() {
        return outboxList;
    }


    public void setInboxList(Set<UserMessage> inboxList) {
        this.inboxList = inboxList;
    }

    public void setOutboxList(Set<UserMessage> outboxList) {
        this.outboxList = outboxList;
    }
    */
    public BeanComparator getDateComparator() {
            return dateComparator;
        }

    public void setDateComparator(BeanComparator dateComparator) {
        this.dateComparator = dateComparator;
    }

    public Set<Friend> getFriends() {
        return friends;
    }

    public void setFriends(Set<Friend> friends) {
        this.friends = friends;
    }

    public Set<FriendRequest> getIncomingFriendRequests() {
        return incomingFriendRequests;
    }

    public void setIncomingFriendRequests(Set<FriendRequest> incomingFriendRequests) {
        this.incomingFriendRequests = incomingFriendRequests;
    }

    public Set<Group> getGroups() {
        return groups;
    }

    public void setGroups(Set<Group> groups) {
        this.groups = groups;
    }
}